from typing import Any, Optional, Generic, TypeVar, Type, Union, get_args
from pydantic import BaseModel, Field
from fastapi.responses import JSONResponse
from src.constants.resultcode import ResultCode
from src.utils.timehelper import TimeHelper

T = TypeVar('T', bound=BaseModel)


class ResponseModel(BaseModel, Generic[T]):
    """统一响应模型"""
    code: int = Field(default=ResultCode.SUCCESS.code, description="响应码")
    message: str = Field(default=ResultCode.SUCCESS.message, description="响应消息")
    data: Optional[T] = Field(default=None, description="响应数据")
    timestamp: int = Field(default_factory=TimeHelper.milliseconds, description="当前时间戳")

    class Config:
        # 允许任意类型，避免泛型类型检查问题
        arbitrary_types_allowed = True


class ApiResponse:
    """API 响应工具类"""

    @staticmethod
    def _serialize_data(data: Any) -> Any:
        """
        序列化数据，处理各种可能的数据类型

        Args:
            data: 需要序列化的数据

        Returns:
            可序列化的数据
        """
        if data is None:
            return None

        # 如果是 Pydantic 模型
        if isinstance(data, BaseModel):
            return data.model_dump()

        # 如果是字典且包含需要序列化的值
        if isinstance(data, dict):
            return {k: ApiResponse._serialize_data(v) for k, v in data.items()}

        # 如果是列表
        if isinstance(data, list):
            return [ApiResponse._serialize_data(item) for item in data]

        # 如果是有 __dict__ 属性的对象（但不是 BaseModel）
        if hasattr(data, '__dict__') and not isinstance(data, BaseModel):
            # 尝试获取可序列化的字典表示
            try:
                return data.__dict__
            except:
                # 如果无法获取 __dict__，尝试其他方法
                pass

        # 如果对象有 to_dict 方法
        if hasattr(data, 'to_dict') and callable(data.to_dict):
            return data.to_dict()

        # 如果对象有 dict 方法
        if hasattr(data, 'dict') and callable(data.dict):
            return data.dict()

        # 对于其他类型，直接返回（JSON 会处理基本类型）
        return data

    @staticmethod
    def success(
            data: Any = None,
            message: Optional[str] = None,
            status_code: int = 200,
    ) -> JSONResponse:
        """
        成功响应
        Args:
            data: 响应数据（Pydantic模型或dict）
            message: 响应消息
            status_code: HTTP状态码
        """
        # 序列化数据
        serialized_data = ApiResponse._serialize_data(data)

        # 创建响应内容
        response_content = {
            "code": ResultCode.SUCCESS.code,
            "message": message or ResultCode.SUCCESS.message,
            "data": serialized_data,
            "timestamp": TimeHelper.milliseconds()
        }

        return JSONResponse(
            status_code=status_code,
            content=response_content
        )

    @staticmethod
    def error(
            result_code: ResultCode,
            data: Any = None,
            message: Optional[str] = None,
            status_code: int = 200,
    ) -> JSONResponse:
        """
        错误响应
        Args:
            result_code: 错误码枚举
            message: 自定义错误消息
            data: 错误详情数据
            status_code: HTTP状态码
        """
        # 序列化数据
        serialized_data = ApiResponse._serialize_data(data)

        # 创建响应内容
        response_content = {
            "code": result_code.code,
            "message": message or result_code.message,
            "data": serialized_data,
            "timestamp": TimeHelper.milliseconds()
        }

        return JSONResponse(
            status_code=status_code,
            content=response_content
        )

    @staticmethod
    def custom(
            code: int,
            message: str,
            data: Any = None,
            status_code: int = 200
    ) -> JSONResponse:
        """
        自定义响应

        Args:
            code: 自定义响应码
            message: 响应消息
            data: 响应数据
            status_code: HTTP状态码
        """
        # 序列化数据
        serialized_data = ApiResponse._serialize_data(data)

        # 创建响应内容
        response_content = {
            "code": code,
            "message": message,
            "data": serialized_data,
            "timestamp": TimeHelper.milliseconds()
        }

        return JSONResponse(
            status_code=status_code,
            content=response_content
        )